
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ddk.h>
#include <nu_api.h>
#include "vmapiidx.h"
#include "vmodem.h"
#include "tapi_cmd.h"
#include "aciimp_cmd.h"
#include "aciimp_rsp.h"
#include "debug.h"
#include "tapierrs.h"


GLOBAL UBYTE toa_merge (T_ACI_TOA type)
{
return   ((type.ton << 4) & 0xF0)
       | ( type.npi       & 0x0F)
       | 0x80;
}

#define vm_MIN(a, b)                    ((a > b) ? b : a)

extern VM_SYSTEM_STATUS g_VMStatus;
extern DzEvent g_indicatorEvent;

T_ACI_CMD_SRC g_ACICmdSrc = CMD_SRC_LCL;
int g_rfopen = 0;
int g_SyncTimeEnabled = 1;
volatile T_ACI_AT_CMD g_current_atcmd = AT_CMD_NONE;
Elastos::UInt32 g_SyncTimeElapsed = 0; 

extern void UpdataRTCTime (UInt32 Elapsed);

#define TIMEOUT_NORMAL     5000
#define TIMEOUT_LONG      20000
#define TIMEOUT_NETWORK  120000

static DzMutex s_callLock;
static DzMutex s_simLock;

#define CALL_LOCK() \
    int _lock_result; \
    s_callLock.Lock(&_lock_result); \
    if (WaitResult_OK != _lock_result) { return E_GEN_NOTREADY; } \

#define SIM_LOCK() \
        int _lock_result; \
        s_simLock.Lock(&_lock_result); \
        if (WaitResult_OK != _lock_result) { return E_GEN_NOTREADY; } \

#define SIM_TRYLOCK(timeout) \
        int _lock_result; \
        s_simLock.TryLock(timeout, &_lock_result); \
        if (WaitResult_OK != _lock_result) { return E_GEN_NOTREADY; } \

#define CALL_UNLOCK() \
    s_callLock.Unlock();

#define SIM_UNLOCK() \
    s_simLock.Unlock();

int getGeneralReturn(
    int ret, T_ACI_AT_CMD cmdId, int timeout, VM_RESPONSE *data = NULL,
    int *retType = NULL)
{
    if (ret == AT_FAIL) {
        ret = E_GEN_INTERNAL;
    }
    else if (ret == AT_CMPL) {
        ret = E_GEN_OK;
    }
    else if (ret == AT_EXCT) {
        ret = getGeneralResponse(cmdId, timeout, data, retType);
    }
    else if (ret == AT_BUSY) {
        ret = E_GEN_NOTREADY;
    }
    return ret;
}

int CALLACI_parseAtCommand(
    /* [in] */ Int32 nControlCode,
    /* [in] */ const MemoryBuf & setData,
    /* [out] */ MemoryBuf * getData)
{
    VM_COMMAND *command = (VM_COMMAND *)setData.GetPayload();
    VM_RESPONSE *response =
        getData ? (VM_RESPONSE *)getData->GetPayload() : NULL;
    int res = E_GEN_INTERNAL;
    switch (nControlCode) {
    case VM_IOCTRL_sAT_PlusCFUN: {
        SIM_LOCK();
        if (command->sAT_PlusCFUN.fun == 5) {
            nu_ACI_GetCommand()->sAT_Abort(
                g_ACICmdSrc,
                AT_CMD_NRG);
            cleanResponseCache(AT_CMD_NRG);
            T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PercentNRG(
                g_ACICmdSrc,
                NRG_RGMD_Auto,
                NRG_SVMD_Limited,
                NRG_FRMT_NotPresent,
                NULL);
            res = getGeneralReturn(
                ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_NRG, 30000);
            VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCFUN -> sAT_PercentNRG res.%x\n", res);
            res = E_GEN_OK;
        }
        else {
            nu_ACI_GetCommand()->sAT_PercentCSQ ( CMD_SRC_LCL, CSQ_Enable );
            nu_ACI_GetCommand()->sAT_Abort(
                g_ACICmdSrc,
                AT_CMD_CFUN);
            nu_ACI_GetCommand()->sAT_Abort(
                g_ACICmdSrc,
                AT_CMD_COPS);
            cleanResponseCache(AT_CMD_CFUN);
            T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCFUN(
                g_ACICmdSrc,
                (T_ACI_CFUN_FUN)command->sAT_PlusCFUN.fun,
                CFUN_RST_NoReset);
            res = getGeneralReturn(
                ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CFUN, TIMEOUT_LONG);
            g_rfopen = (command->sAT_PlusCFUN.fun == CFUN_FUN_Full) ? 1 : 0;
            if (command->sAT_PlusCFUN.fun == CFUN_FUN_Full
                    && res != E_CME_SIMPINREQUIRED) { //Bug20422
                cleanResponseCache(AT_CMD_COPS);
                T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCOPS(
                    g_ACICmdSrc,
                    COPS_MOD_Auto,
                    COPS_FRMT_Numeric,
                    NULL);
                res = getGeneralReturn(
                    ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_COPS, 30000);
                VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCFUN -> sAT_PlusCOPS res.%x\n", res);
                res = E_GEN_OK;
            }
        }
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_qAT_PlusCFUN: {
        SIM_LOCK();
        T_ACI_CFUN_FUN fun;
        cleanResponseCache(AT_CMD_CFUN);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCFUN(
            g_ACICmdSrc,
            &fun);
        //VM_LOG("1VM_IOCTRL_qAT_PlusCFUN-> ret.%d,res.%d\n", ret, res);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CFUN, TIMEOUT_NORMAL);
        if (res == E_GEN_OK) {
            response->qAT_PlusCFUN.fun = fun;
        }
        VM_LOG("2VM_IOCTRL_qAT_PlusCFUN-> ret.%d,res.%d\n", ret, res);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_qAT_PlusCIMI: {
        SIM_LOCK();
        cleanResponseCache(AT_CMD_CIMI);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCIMI(
            g_ACICmdSrc,
            response->qAT_PlusCIMI.cimi);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CIMI, TIMEOUT_NORMAL);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCSQ: {
        SIM_LOCK();
        UBYTE rssi;
        UBYTE ber;
        UBYTE actrssilevel;
        nu_ACI_GetCommand()->qAT_PercentCSQ(
            g_ACICmdSrc,
            &rssi,
            &ber,
            &actrssilevel);
        VM_LOG("VM_IOCTRL_qAT_PlusCSQ-> rssi.%d ber.%d csq.%d\n",
            rssi, ber, actrssilevel);
        response->qAT_PlusCSQ.csq = actrssilevel;
        SIM_UNLOCK();
        return E_GEN_OK;
    }
        break;

    case VM_IOCTRL_sAT_PercentALS: {
        SIM_LOCK();
        struct VM_CMD_sAT_PercentALS *als = &command->sAT_PercentALS;
        cleanResponseCache(AT_CMD_ALS);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PercentALS(
            g_ACICmdSrc,
            (T_ACI_ALS_MOD)als->alsMode);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_ALS, TIMEOUT_NORMAL);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_qAT_PercentALS: {
        SIM_LOCK();
        struct VM_RSP_qAT_PercentALS *als = &response->qAT_PercentALS;
        T_ACI_ALS_MOD alsMode;
        if (nu_ACI_GetCommand()->qAT_PercentALS(
            g_ACICmdSrc,
            &alsMode) == AT_CMPL) {
            als->alsMode = alsMode;
            VM_LOG("VM_IOCTRL_qAT_PercentALS-> alsMode.%d\n", alsMode);
            SIM_UNLOCK();
            return E_GEN_OK;
        }
        SIM_UNLOCK();
        return E_GEN_INTERNAL;
    }
        break;

    case VM_IOCTRL_sAT_PlusCGSN: {
        SIM_LOCK();
        struct VM_RSP_sAT_PlusCGSN *imei = &response->sAT_PlusCGSN;
        if (nu_ACI_GetCommand()->sAT_PlusCGSN(
            g_ACICmdSrc,
            imei->imei) == AT_CMPL) {
            SIM_UNLOCK();
            return E_GEN_OK;
        }
        SIM_UNLOCK();
        return E_GEN_INTERNAL;
    }

    case VM_IOCTRL_sAT_PlusCCLK: {
        struct VM_CMD_sAT_PlusCCLK *dt = &command->sAT_PlusCCLK;
        T_ACI_RTC_DATE date;
        T_ACI_RTC_TIME time;
        date.day = dt->day;
        date.month = dt->month;
        date.year = dt->year;

        time.hour = dt->hour;
        time.minute = dt->minute;
        time.second = dt->second;

        time.format = (T_ACI_RTC_TIME_FORMAT)dt->format;
        time.PM_flag = dt->PM_flag;

        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCCLK -> y.%d,m.%d,d.%d,h.%d,m.%d,s.%d fmt.%d flag.%d\n",
            date.year, date.month, date.day,
            time.hour, time.minute, time.second, time.format, time.PM_flag);

        SIM_LOCK();
        if (nu_ACI_GetCommand()->sAT_PlusCCLK(
            g_ACICmdSrc, &date, &time) == AT_CMPL) {
            SIM_UNLOCK();
            return E_GEN_OK;
        }
        SIM_UNLOCK();
        return E_GEN_INTERNAL;
    }
        break;

    case VM_IOCTRL_qAT_PlusCCLK: {
        SIM_LOCK();
        T_ACI_RTC_DATE date;
        T_ACI_RTC_TIME time;
        if (nu_ACI_GetCommand()->qAT_PlusCCLK(
            g_ACICmdSrc, &date, &time) == AT_CMPL) {
            SIM_UNLOCK();
            response->qAT_PlusCCLK.year = date.year;
            response->qAT_PlusCCLK.month = date.month;
            response->qAT_PlusCCLK.day = date.day;
            response->qAT_PlusCCLK.hour = time.hour;
            response->qAT_PlusCCLK.minute = time.minute;
            response->qAT_PlusCCLK.second = time.second;
            response->qAT_PlusCCLK.format = time.format;
            response->qAT_PlusCCLK.PM_flag = time.PM_flag;
            VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCCLK -> y.%d,m.%d,d.%d,h.%d,m.%d,s.%d fmt.%d flag.%d\n",
                date.year, date.month, date.day,
                time.hour, time.minute, time.second, time.format, time.PM_flag);
            return E_GEN_OK;
        }
        SIM_UNLOCK();
        return E_GEN_INTERNAL;
    }

    case  VM_IOCTRL_tAT_PlusCPBR: {
        SIM_LOCK();
        SHORT        firstIdx;
        SHORT        lastIdx;
        UBYTE        nlength;
        UBYTE        tlength;
        cleanResponseCache(AT_CMD_CPBR);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->tAT_PlusCPBR(
            g_ACICmdSrc,
            &firstIdx,
            &lastIdx,
            &nlength,
            &tlength);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPBR, TIMEOUT_NORMAL);
        if (res == E_GEN_OK) {
            response->tAT_PlusCPBR.firstIdx = firstIdx;
            response->tAT_PlusCPBR.lastIdx = lastIdx;
            response->tAT_PlusCPBR.nlength = nlength;
            response->tAT_PlusCPBR.tlength = tlength;
        }
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCPBR: {
        SIM_LOCK();
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCPBS(
            g_ACICmdSrc, (T_ACI_PB_STOR)command->sAT_PlusCPBR.location, NULL);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPBR -> ret.%d loc.%d\n",
            ret, command->sAT_PlusCPBR.location);

        int timeLimit = 1000;
        while (g_VMStatus.pbStatus == PB_STAT_Blocked && timeLimit-- > 0) {
            DzSleep(1, NULL); }

        SHORT          startIdx = command->sAT_PlusCPBR.startIndex;
        SHORT          lastIdx;
        T_ACI_PB_ENTR  pbLst[MAX_PB_ENTR];
        int remain = command->sAT_PlusCPBR.count;
        int count = 0;
        while (remain > 0) {
            int toread = (remain > MAX_PB_ENTR) ? MAX_PB_ENTR : remain;
            cleanResponseCache(AT_CMD_CPBR);
            T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCPBR(
                g_ACICmdSrc,
                startIdx,
                startIdx + toread - 1,
                &lastIdx,
                pbLst);
            int res = getGeneralReturn(
                ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPBR, TIMEOUT_NORMAL);
            VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPBR -> startIdx.%d,toread.%d,ret.%d,res.%d\n",
                startIdx, toread, ret, res);
            remain -= MAX_PB_ENTR;
            if (res == E_GEN_OK) {
                for (int i = 0; i < toread; i++) {
                    if (pbLst[i].index == -1) { break; }
                    response->sAT_PlusCPBR.entry[count].index = pbLst[i].index;
                    strcpy(
                        response->sAT_PlusCPBR.entry[count].number,
                        pbLst[i].number);
                    response->sAT_PlusCPBR.entry[count].ton = pbLst[i].type.ton;
                    response->sAT_PlusCPBR.entry[count].npi = pbLst[i].type.npi;
                    memcpy(
                        response->sAT_PlusCPBR.entry[count].text,
                        pbLst[i].text.data,
                        pbLst[i].text.len);
                    response->sAT_PlusCPBR.entry[count].textSize =
                        pbLst[i].text.len;
                    response->sAT_PlusCPBR.entry[count].line = pbLst[i].line;
                    VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPBR -> idx.%d %s\n",
                        response->sAT_PlusCPBR.entry[count].index,
                        response->sAT_PlusCPBR.entry[count].number);
                    count++;
                }
            }
            startIdx = lastIdx + 1;
        }
        response->sAT_PlusCPBR.count = count;
        SIM_UNLOCK();
        return E_GEN_OK;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCPBS: {
        SIM_LOCK();
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCPBS(
            g_ACICmdSrc, (T_ACI_PB_STOR)command->qAT_PlusCPBS.location, NULL);
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCPBS -> ret.%d loc.%d\n",
            ret, command->qAT_PlusCPBS.location);

        T_ACI_PB_STOR storage;
        SHORT         used;
        SHORT         total;
        cleanResponseCache(AT_CMD_CPBS);
        ret = nu_ACI_GetCommand()->qAT_PlusCPBS(
            g_ACICmdSrc,
            &storage,
            &used,
            &total);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPBS, TIMEOUT_NORMAL);
        if (res == E_GEN_OK) {
            response->qAT_PlusCPBS.used = used;
            response->qAT_PlusCPBS.total = total;
        }
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCPBS -> res.%d used.%d total.%d\n",
            res, response->qAT_PlusCPBS.used, response->qAT_PlusCPBS.total);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCPIN: {
        SIM_LOCK();

        T_ACI_CPIN_RSLT pinLst;
        int res = 0;
        cleanResponseCache(AT_CMD_CPIN);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCPIN(
            g_ACICmdSrc,
            &pinLst);
        if (AT_EXCT == ret) {
            res = getGeneralReturn(
                        ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPIN, TIMEOUT_NORMAL, response);
        }
        else {
            res = getGeneralReturn(
                        ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPIN, TIMEOUT_NORMAL);
            if (res == E_GEN_OK) {
                response->qAT_PlusCPIN.pin = pinLst;
            }
        }
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCPIN -> res.%d pin.%d pinLst.%d\n",
            res, response->qAT_PlusCPIN.pin, pinLst);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCPBW: {
        SIM_LOCK();
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCPBS(
            g_ACICmdSrc, (T_ACI_PB_STOR)command->sAT_PlusCPBW.location, NULL);

        int timeLimit = 1000;
        while (g_VMStatus.pbStatus == PB_STAT_Blocked && timeLimit-- > 0) {
            DzSleep(1, NULL); }
        struct VM_CMD_sAT_PlusCPBW *cpbw = &command->sAT_PlusCPBW;

        SHORT         index = cpbw->index;
        CHAR          *number =
            cpbw->number[0] == '\0' ? NULL : cpbw->number;
        T_ACI_TOA     type;
        type.ton = (T_ACI_TOA_TON)cpbw->ton;
        type.npi = (T_ACI_TOA_NPI)cpbw->npi;
        T_ACI_TOA     *type_ptr =
            (type.ton == TON_NotPresent && type.npi == NPI_NotPresent) ?
            NULL : &type;

        T_ACI_PB_TEXT text, *p_text = NULL;
        text.len = 0;
        text.cs = CS_Sim;
        if (cpbw->params & VM_CMD_sAT_PlusCPBW::cpbw_text) {
            text.len = vm_MIN(MAX_PHB_NUM_LEN, cpbw->textSize);
            memcpy(text.data, cpbw->text, text.len);
            p_text = &text;
        }

        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPBW -> ret.%d loc.%d size.%d len.%d\n",
            ret, command->sAT_PlusCPBW.location, cpbw->textSize, text.len);
        cleanResponseCache(AT_CMD_CPBW);
        ret = nu_ACI_GetCommand()->sAT_PlusCPBW(
            g_ACICmdSrc,
            index,
            number,
            type_ptr,
            p_text,
            NULL);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPBW, TIMEOUT_NORMAL);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCPIN: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCPIN *cpin = &command->sAT_PlusCPIN;
        CHAR *pin = cpin->password[0] == '\0' ? NULL : cpin->password;
        CHAR *newPin = cpin->newPin[0] == '\0' ? NULL : cpin->newPin;
        cleanResponseCache(AT_CMD_CPIN);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCPIN(
            g_ACICmdSrc,
            pin,
            newPin);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPIN, TIMEOUT_NORMAL);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPIN ->"            \
            "res.%d pin.%s newPin.%s\n",
            res, pin?pin:"NULL", newPin?newPin:"NULL");
        if (res == E_GEN_OK && g_rfopen) {
            cleanResponseCache(AT_CMD_COPS);
            ret = nu_ACI_GetCommand()->sAT_PlusCOPS(
                g_ACICmdSrc,
                COPS_MOD_Auto,
                COPS_FRMT_Numeric,
                NULL);
            getGeneralReturn(
                ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_COPS, TIMEOUT_LONG);
            SIM_UNLOCK();
            return E_GEN_OK;
        }
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PercentPVRF: {
        SIM_LOCK();
        SHORT        pn1Cnt;
        SHORT        pn2Cnt;
        SHORT        pk1Cnt;
        SHORT        pk2Cnt;
        T_ACI_PVRF_STAT ps1;
        T_ACI_PVRF_STAT ps2;
        cleanResponseCache(AT_CMD_PVRF);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PercentPVRF(
            g_ACICmdSrc,
            &pn1Cnt,
            &pn2Cnt,
            &pk1Cnt,
            &pk2Cnt,
            &ps1,
            &ps2);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_PVRF, TIMEOUT_NORMAL);
        if (res == E_GEN_OK) {
            response->qAT_PercentPVRF.pin1 = pn1Cnt;
            response->qAT_PercentPVRF.pin2 = pn2Cnt;
            response->qAT_PercentPVRF.puk1 = pk1Cnt;
            response->qAT_PercentPVRF.puk2 = pk2Cnt;
        }
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PercentPVRF ->"            \
            "res.%d pin1.%d pin2.%d puk1.%d puk2.%d\n",
            res,
            response->qAT_PercentPVRF.pin1,
            response->qAT_PercentPVRF.pin2,
            response->qAT_PercentPVRF.puk1,
            response->qAT_PercentPVRF.puk2);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCLCK: {
        SIM_LOCK();
        int res = E_GEN_OK;
        struct VM_CMD_qAT_PlusCLCK *clck = &command->qAT_PlusCLCK;
        T_ACI_CLCK_FAC fac = (T_ACI_CLCK_FAC)clck->fac;
        T_ACI_CLASS class_type = (T_ACI_CLASS)clck->class_type;

        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCLCK -> in fac.%d class_type.%d\n",
            fac, class_type);
        T_ACI_CLSSTAT clsStat;
        cleanResponseCache(AT_CMD_CLCK);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCLCK(
            g_ACICmdSrc,
            fac,
            class_type,
            &clsStat);
        if (AT_CMPL == ret) {
            VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCLCK 1-> res.%d active.%d(%d) class_type.%d(%d)\n",
                res,
                response->qAT_PlusCLCK.status, clsStat.status,
                response->qAT_PlusCLCK.class_type, clsStat.class_type);

            response->qAT_PlusCLCK.class_type = (int)clsStat.class_type;
            response->qAT_PlusCLCK.status = clsStat.status;
        }
        else {
            res = getGeneralReturn(
                ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CLCK, TIMEOUT_LONG, response);

            VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCLCK 2-> res.%d active.%d(%d) class_type.%d(%d)\n",
                res,
                response->qAT_PlusCLCK.status, clsStat.status,
                response->qAT_PlusCLCK.class_type, clsStat.class_type);
        }
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCLCK: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCLCK *p = &command->sAT_PlusCLCK;
        T_ACI_CLCK_FAC fac = (T_ACI_CLCK_FAC)p->fac;
        T_ACI_CLCK_MOD mode = (T_ACI_CLCK_MOD)p->active;
        T_ACI_CLASS class_type = (T_ACI_CLASS)p->class_type;
        CHAR *password =
            (p->params & VM_CMD_sAT_PlusCLCK::clck_password) ?
            p->password : NULL;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCLCK fac.%d mode.%d class_type.%d pw.%s\n",
            fac, mode, class_type, password);
        cleanResponseCache(AT_CMD_CLCK);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCLCK(
            g_ACICmdSrc,
            fac,
            mode,
            password,
            class_type);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CLCK, TIMEOUT_NORMAL);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCLCK res.%d ret.%d\n", res, ret);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PlusCPWD: {
        SIM_LOCK();
        VM_CMD_sAT_PlusCPWD *p = &command->sAT_PlusCPWD;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPWD fac.%d old.%s new.%s\n",
            p->fac, p->oldPwd, p->newPwd);
        cleanResponseCache(AT_CMD_CPWD);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCPWD(
            g_ACICmdSrc,
            (T_ACI_CPWD_FAC)p->fac,
            p->oldPwd,
            p->newPwd);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPWD, TIMEOUT_NORMAL, response);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPWD -> res.%x ret.%d\n", res, ret);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCPMS: {
        SIM_TRYLOCK(100);
        cleanResponseCache(AT_CMD_CPMS);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCPMS(
            g_ACICmdSrc);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CPMS, TIMEOUT_NORMAL, response);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCMGL: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCMGL *cmgl = &command->sAT_PlusCMGL;
        T_ACI_SMS_STAT    state = (T_ACI_SMS_STAT)cmgl->stat;
        SHORT             startIdx = 0;
        T_ACI_SMS_READ    rdMode = (T_ACI_SMS_READ)cmgl->readMode;
        cleanResponseCache(AT_CMD_CMGL);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCMGL(
            g_ACICmdSrc,
            state,
            startIdx,
            rdMode);
        VM_LOG("VM_LOG: sAT_PlusCMGL -> ret.%d\n", ret);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CMGL, TIMEOUT_NORMAL);
        if (res == E_GEN_OK) { // BUGBUG:
        }
        VM_LOG("VM_LOG: sAT_PlusCMGL -> res.%d\n", res);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCMGR: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCMGR *cmgr = &command->sAT_PlusCMGR;
        SHORT             index = cmgr->index;
        T_ACI_SMS_READ    rdMode = (T_ACI_SMS_READ)cmgr->readMode;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCMGR -> index.%d rdMode.%d\n",
            index, rdMode);
        nu_ACI_GetCommand()->sAT_Abort(
            g_ACICmdSrc,
            AT_CMD_CMGS);
        nu_ACI_GetCommand()->sAT_Abort(
            g_ACICmdSrc,
            AT_CMD_CMGR);
        cleanResponseCache(AT_CMD_CMGR);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCMGR(
            g_ACICmdSrc,
            index,
            rdMode);
        int type = 0;
        int res = getGeneralReturn(
            ret, AT_CMD_CMGR, 20000, response, &type); // Long Timeout
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCMGR -> res.%d ret.%d,type.%d\n", res, ret, type);
        if (res == E_GEN_OK && type == VM_GR_CMGR) {
            SIM_UNLOCK();
            return E_GEN_OK;
        }
        SIM_UNLOCK();
        return E_GEN_TIMEOUT;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCMGD: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCMGD *cmgd = &command->sAT_PlusCMGD;
        SHORT           index = cmgd->index;
        UBYTE           status = cmgd->mode;
        cleanResponseCache(AT_CMD_CMGD);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCMGD(
            g_ACICmdSrc,
            index,
            status);
        getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CMGD, 20000);
        SIM_UNLOCK();
        return E_GEN_OK;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCSIM: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCSIM *csim = &command->sAT_PlusCSIM;
        cleanResponseCache(AT_CMD_CSIM);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCSIM(
            g_ACICmdSrc,
            csim->dataLen,
            csim->data);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CSIM, TIMEOUT_NORMAL, response);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCRSM: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCRSM *crsm = &command->sAT_PlusCRSM;
        cleanResponseCache(AT_CMD_CRSM);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCRSM(
            g_ACICmdSrc,
            (T_ACI_CRSM_CMD)crsm->cmd,
            crsm->fileId,
            crsm->p1,
            crsm->p2,
            crsm->p3,
            crsm->dataLen,
            crsm->data);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME | VM_GR_CRSM, */ AT_CMD_CRSM, TIMEOUT_NORMAL,
            response);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCMGW: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCMGW *cmgw = &command->sAT_PlusCMGW;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCMGW -> in index.%d stat.%d ref.%d\n",
            cmgw->index, cmgw->stat, cmgw->msg_ref);

        static T_ACI_SM_DATA tmp;
        memcpy(tmp.data, cmgw->data, cmgw->len);
        tmp.len = cmgw->len;

        T_SM_DATA_EXT  data;
        data.len = cmgw->len;
        data.data = tmp.data;
        cleanResponseCache(AT_CMD_CMGW);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCMGW(
            g_ACICmdSrc,
            (SHORT)cmgw->index,    //index
            cmgw->address,
            NULL, //&(cmgw->toa),
            (T_ACI_SMS_STAT)cmgw->stat,
            cmgw->msg_ref,
            &data,
            cmgw->sca,
            NULL, //&(cmgw->tosca),
            FALSE);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCMGW -> ret.%d\n", ret);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CMGW, TIMEOUT_NORMAL, response);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCMGW -> res.x%08x\n",
            res);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCMGWPdu: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCMGWPdu *p = &command->sAT_PlusCMGWPdu;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCMGWPdu -> in stat.%d\n", p->stat);

        T_ACI_SM_DATA tmp;
        assert(p->len <= VM_MAX_SM_LEN);
        memcpy(tmp.data, p->pdu, p->len);
        tmp.len = p->len;
        cleanResponseCache(AT_CMD_CMGW);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCMGWPdu(
            g_ACICmdSrc, p->stat, &tmp);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CMGW, TIMEOUT_NORMAL, response);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCMGWPdu -> res.x%08x ret.%d\n",
            res, ret);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PlusCUSD: {
        SIM_LOCK();
        cleanResponseCache(AT_CMD_CUSD);
        struct VM_CMD_sAT_PlusCUSD *p = &command->sAT_PlusCUSD;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCUSD -> in len.%d state.%d dcs.%d\n",
            p->len, p->state, p->dcs);

        T_ACI_RETURN ret;
        if (p->state == 2) {
            ret = nu_ACI_GetCommand()->sAT_end_ussd(g_ACICmdSrc);
        }
        else {
            ret = nu_ACI_GetCommand()->sAT_PlusCUSD(
                g_ACICmdSrc, (T_ACI_USSD_DATA*)p, p->dcs);
        }

        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CUSD, TIMEOUT_NORMAL);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCUSD -> res.x%08x ret.%d\n",
            res, ret);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCNMI: {
        SIM_LOCK();
        struct VM_CMD_sAT_PlusCNMI *cnmi = &command->sAT_PlusCNMI;
        T_ACI_CNMI_MT     mt = (T_ACI_CNMI_MT)cnmi->sm;
        T_ACI_CNMI_BM     bm = (T_ACI_CNMI_BM)cnmi->cbm;
        T_ACI_CNMI_DS     ds = (T_ACI_CNMI_DS)cnmi->ds;
        cleanResponseCache(AT_CMD_CNMI);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCNMI(
            g_ACICmdSrc,
            mt,
            bm,
            ds);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CNMI, TIMEOUT_NORMAL);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCNMI -> res.x%08x ret.%d mt.%d bm.%d, ds.%d\n",
            res, ret, mt, bm, ds);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCNMI: {
        SIM_LOCK();
        cleanResponseCache(AT_CMD_CNMI);
        struct VM_RSP_qAT_PlusCNMI *cnmi = &response->qAT_PlusCNMI;
        T_ACI_CNMI_MT     mt;
        T_ACI_CNMI_BM     bm;
        T_ACI_CNMI_DS     ds;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCNMI(
            g_ACICmdSrc,
            &mt,
            &bm,
            &ds);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CNMI, TIMEOUT_NORMAL);
        if (res == E_GEN_OK) {
            cnmi->sm = mt;
            cnmi->cbm = bm;
            cnmi->ds = ds;
        }
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCNMI -> res.x%08x ret.%d mt.%d bm.%d, ds.%d\n",
            res, ret, mt, bm, ds);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCMGS: {
        SIM_TRYLOCK(0);
#if 0
        nu_ACI_GetCommand()->sAT_Abort(
            g_ACICmdSrc,
            AT_CMD_CMGS);
        nu_ACI_GetCommand()->sAT_Abort(
            g_ACICmdSrc,
            AT_CMD_CMGR);
#endif
        cleanResponseCache(AT_CMD_CMGS);
        struct VM_CMD_sAT_PlusCMGS *cmgs = &command->sAT_PlusCMGS;
        T_ACI_SM_DATA pdu;
        memcpy(pdu.data, cmgs->data, cmgs->len);
        pdu.len = cmgs->len;
        g_current_atcmd = AT_CMD_CMGS;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCMGSPdu(
            g_ACICmdSrc,
            &pdu);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CMGS, 20000, response);
        VM_LOG("VM_LOG: sAT_PlusCMGSPdu -> res.x%08x\n", res);
        g_current_atcmd = AT_CMD_NONE;
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCSCA: {
        SIM_TRYLOCK(100);
        cleanResponseCache(AT_CMD_CSCA);
        struct VM_RSP_qAT_PlusCSCA *csca = &response->qAT_PlusCSCA;
        CHAR            sca[21];
        T_ACI_TOA       tosca;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCSCA(
            g_ACICmdSrc,
            sca,
            &tosca);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CSCA, TIMEOUT_NORMAL);
        if (res == E_GEN_OK) {
            if (tosca.ton == TON_International) {
                csca->sca[0] = '+';
                strcpy(csca->sca + 1, sca);
            }
            else {
                strcpy(csca->sca, sca);
            }
            csca->tosca = toa_merge(tosca);
        }
        VM_LOG("VM_LOG: qAT_PlusCSCA -> res.x%08x\n", res);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCSCA: {
        SIM_LOCK();
        cleanResponseCache(AT_CMD_CSCA);
        struct VM_CMD_sAT_PlusCSCA *csca = &command->sAT_PlusCSCA;
        CHAR            *sca =
            csca->sca[0] == '+' ? csca->sca + 1 : csca->sca;
        T_ACI_TOA       tosca;
        tosca.ton = (T_ACI_TOA_TON)((csca->tosca >> 4) & 0x07);
        tosca.npi = (T_ACI_TOA_NPI)(csca->tosca & 0x0F);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCSCA(
            g_ACICmdSrc,
            sca,
            &tosca);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CSCA, TIMEOUT_NORMAL);
        nu_ACI_GetCommand()->sAT_PlusCSAS(g_ACICmdSrc, 1);
        VM_LOG("VM_LOG: sAT_PlusCSCA -> res.x%08x\n", res);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCSCB: {
        SIM_LOCK();
        cleanResponseCache(AT_CMD_CSCB);
        struct VM_CMD_sAT_PlusCSCB *cscb = &command->sAT_PlusCSCB;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCSCB(
            g_ACICmdSrc,
            (T_ACI_CSCB_MOD)cscb->mode,
            (USHORT*)cscb->mids,
            (U8*)cscb->dcss);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CSCB, TIMEOUT_NORMAL);
        nu_ACI_GetCommand()->sAT_PlusCSAS(g_ACICmdSrc, 1);
        VM_LOG("VM_LOG: sAT_PlusCSCB -> res.x%08x\n", res);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCSCB: {
        SIM_LOCK();
        cleanResponseCache(AT_CMD_CSCB);
        struct VM_RSP_qAT_PlusCSCB *cscb = &response->qAT_PlusCSCB;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCSCB(
            g_ACICmdSrc,
            (T_ACI_CSCB_MOD*)&cscb->mode,
            &cscb->c_mids,
            (USHORT*)cscb->mids,
            &cscb->c_dcss,
            (U8*)cscb->dcss);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CMS, */ AT_CMD_CSCB, TIMEOUT_NORMAL);
        VM_LOG("VM_LOG: qAT_PlusCSCB -> res.x%08x\n", res);
        SIM_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_Dn: {
        SIM_LOCK();
        struct VM_CMD_sAT_Dn *dialing = &command->sAT_Dn;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_Dn(
            g_ACICmdSrc,
            dialing->phoneNumer,
            D_CLIR_OVRD_Default,
            D_CUG_CTRL_NotPresent,
            D_TOC_Voice);
        if (ret == AT_CMPL || ret == AT_EXCT) {
            SIM_UNLOCK();
            return E_GEN_OK;
        }
        else if (ret == AT_FDN_ONLY)
        {
            SIM_UNLOCK();
            return E_CUS_FDNONLY;
        }
        SIM_UNLOCK();
        return E_GEN_INTERNAL;
    }
        break;

    case  VM_IOCTRL_sAT_Abort: {
        cleanResponseCache(AT_CMD_ABRT);
        struct VM_CMD_sAT_Abort *abort = &command->sAT_Abort;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_Abort(
            g_ACICmdSrc,
            (T_ACI_AT_CMD)abort->cmdId);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_ABRT, TIMEOUT_LONG);
        if (res == E_GEN_OK) {
        }
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCHLD: {
        CALL_LOCK();
        cleanResponseCache(AT_CMD_CHLD);
        VM_CMD_sAT_PlusCHLD *chld = &command->sAT_PlusCHLD;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCHLD(
            g_ACICmdSrc,
            (T_ACI_CHLD_MOD) chld->mode,
            (chld->params & VM_CMD_sAT_PlusCHLD::chld_call) ? chld->call : 0);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CHLD, TIMEOUT_LONG);
        if (res == E_GEN_OK) {
        }
        VM_LOG("VM_LOG: sAT_PlusCHLD -> mode.%x ret.%d id.%s\n", chld->mode,
            ret,
            (chld->params & VM_CMD_sAT_PlusCHLD::chld_call) ? chld->call : "");
        CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_H: {
        CALL_LOCK();
        VM_LOG("VM_LOG: sAT_H\n");
        cleanResponseCache(AT_CMD_H);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_H(
            g_ACICmdSrc, FALSE);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_H, TIMEOUT_LONG);
        if (res == E_GEN_OK) {
        }
        CALL_UNLOCK();
        return res;
    }
        break;

	case  VM_IOCTRL_sAT_SAT_H: {
		CALL_LOCK();
        VM_LOG("VM_LOG: sAT_SAT_H\n");
        cleanResponseCache(AT_CMD_H);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_H(
            g_ACICmdSrc, TRUE);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_H, TIMEOUT_LONG);
        if (res == E_GEN_OK) {
        }
		CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCHUP: {
        CALL_LOCK();
        VM_LOG("VM_LOG: sAT_PlusCHUP\n");
        cleanResponseCache(AT_CMD_CHUP);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_H(
            g_ACICmdSrc, FALSE);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CHUP, TIMEOUT_LONG);
        if (res == E_GEN_OK) {
        }
        CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_A: {
        CALL_LOCK();
        VM_LOG("VM_LOG: sAT_A\n");
        cleanResponseCache(AT_CMD_A);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_A(
            g_ACICmdSrc, FALSE);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_A, TIMEOUT_LONG);
        CALL_UNLOCK();
        return res;
    }
        break;

	case  VM_IOCTRL_sAT_SAT_A: {
        CALL_LOCK();
        VM_LOG("VM_LOG: sAT_SAT_A\n");
        cleanResponseCache(AT_CMD_A);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_A(
            g_ACICmdSrc, TRUE);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_A, TIMEOUT_LONG);
        CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCMUT: {
        VM_CMD_sAT_PlusCMUT *p = &command->sAT_PlusCMUT;
        VM_LOG("VM_LOG: VM_CMD_sAT_PlusCMUT mute.%d\n", p->mute);
        cleanResponseCache(AT_CMD_CMUT);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCMUT(
            g_ACICmdSrc, p->mute);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CMUT, TIMEOUT_NORMAL);
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusVTS: {
        CALL_LOCK();
        VM_CMD_sAT_PlusVTS *vts = &command->sAT_PlusVTS;
        VM_LOG("VM_LOG: sAT_PlusVTS -> dtmf.%d, duration.%d\n",
            vts->dtmf, vts->duration);
        cleanResponseCache(AT_CMD_VTS);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusVTS(
            g_ACICmdSrc, vts->dtmf, VTS_MOD_Auto, vts->duration);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_VTS, TIMEOUT_NORMAL);
        CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PercentCREG: {
        CALL_LOCK();
        T_ACI_CREG_STAT stat;
        USHORT          lac;
        USHORT          cid;
        U8              gprs_ind;
        U8              rt;
        cleanResponseCache(AT_CMD_P_CREG);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PercentCREG(
            g_ACICmdSrc,
            &stat,
            &lac,
            &cid,
            &gprs_ind,
            &rt);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_P_CREG, TIMEOUT_LONG);
        if (res == E_GEN_OK) {
            response->qAT_PercentCREG.stat = stat;
            response->qAT_PercentCREG.accTech = rt;
        }
        CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_sAT_PlusCOPS: {
        CALL_LOCK();
        struct VM_CMD_sAT_PlusCOPS *cops = &command->sAT_PlusCOPS;
        T_ACI_COPS_MOD  mode = (T_ACI_COPS_MOD)cops->mode;
        T_ACI_COPS_FRMT format = (T_ACI_COPS_FRMT)cops->format;
        CHAR * oper = (cops->params & VM_CMD_sAT_PlusCOPS::cops_name) ?
            cops->name : NULL;
        cleanResponseCache(AT_CMD_COPS);
        g_current_atcmd = AT_CMD_COPS;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCOPS(
            g_ACICmdSrc,
            mode,
            format,
            oper);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_COPS, TIMEOUT_NETWORK);
        g_current_atcmd = AT_CMD_NONE;
        CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCOPS: {
        CALL_LOCK();
        T_ACI_RETURN ret;
        int res = 0;
        cleanResponseCache(AT_CMD_COPS);
        ret = nu_ACI_GetCommand()->sAT_PlusCOPS(
            g_ACICmdSrc,
            COPS_MOD_SetOnly,
            COPS_FRMT_Numeric,
            NULL);
        res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_COPS, TIMEOUT_NORMAL);
        VM_LOG("VM_LOG: sAT_PlusCOPS COPS_FRMT_Numeric -> res.%d,ret.%d\n", res, ret);

        T_ACI_COPS_MOD mode;
        T_ACI_COPS_FRMT format;
        CHAR oper[MAX_ALPHA_OPER_LEN] = "";
        cleanResponseCache(AT_CMD_COPS);
        g_current_atcmd = AT_CMD_COPS;
        ret = nu_ACI_GetCommand()->qAT_PlusCOPS(
            g_ACICmdSrc,
            &mode,
            &format,
            oper);
        res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_COPS, TIMEOUT_NORMAL);
        if (res == E_GEN_OK) {
            struct VM_RSP_qAT_PlusCOPS *cops = &response->qAT_PlusCOPS;
            cops->mode = mode;
            cops->format = format;
            int len = sizeof(cops->numName)-1;
            strncpy(cops->numName, oper, len);
            cops->numName[len] = 0;
            VM_LOG("VM_LOG: qAT_PlusCOPS -> OK. mode.%d,format.%d oper.%s\n",
                mode, format, oper);
        }
        else {
            VM_LOG("VM_LOG: qAT_PlusCOPS -> failed. ret.%d\n", ret);
        }
        g_current_atcmd = AT_CMD_NONE;
        CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_CLCC: {
        CALL_LOCK();
        VM_RSP_qAT_PlusCLCC *clcc = response->qAT_PlusCLCC;
        T_ACI_CLCC_CALDESC calLst[MAX_CALL_NR];
        cleanResponseCache(AT_CMD_CLCC);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCLCC(
            g_ACICmdSrc,
            calLst);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CLCC, TIMEOUT_LONG);
        if (res == E_GEN_OK) {
            int actual = 0;
            for (int i = 0; i < MAX_CALL_NR && i < 7; i++) {
                VM_LOG("VM_LOG: qAT_CLCC -> i.%d, idx.%x actual.%d\n",
                    i, calLst[i].idx, actual);
                VM_LOG("VM_LOG: qAT_CLCC -> i.%d, mode.%d\n", i, calLst[i].mode);
                VM_LOG("VM_LOG: qAT_CLCC -> i.%d, stat.%d\n", i, calLst[i].stat);
                VM_LOG("VM_LOG: qAT_CLCC -> i.%d, mpty.%d\n", i, calLst[i].mpty);
                if (calLst[i].idx == ACI_NumParmNotPresent) { break; }
                clcc[actual].idx = calLst[i].idx;
                clcc[actual].dir = calLst[i].dir;
                clcc[actual].stat = calLst[i].stat;
                clcc[actual].mode = calLst[i].mode;
                clcc[actual].mpty = calLst[i].mpty;
                clcc[actual].class_type = calLst[i].class_type;
                strcpy(clcc[actual].number,calLst[i].number);
                clcc[actual].type =
                    ((calLst[i].type.ton << 4) + calLst[i].type.npi);
                //clcc[actual].alpha = calLst[i].alpha;
                actual++;
            }
            clcc[actual].idx = -1;
        }
        CALL_UNLOCK();
        return res;
    }
        break;

    case  VM_IOCTRL_qAT_PlusCGREG: {
        CALL_LOCK();
        T_CGREG_STAT stat;
        USHORT          lac;
        USHORT          cid;
        cleanResponseCache(AT_CMD_CGREG);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCGREG(
            g_ACICmdSrc,
            &stat,
            &lac,
            &cid);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CGREG, TIMEOUT_LONG);
        if (res == E_GEN_OK) {
            response->qAT_PlusCGREG.stat = stat;
        }
        CALL_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_qAT_PlusCGDCONT: {
        CALL_LOCK();
        T_PDP_CONTEXT pdp_context_array[PDP_CONTEXT_CID_MAX];
        U8 cid_array[PDP_CONTEXT_CID_MAX];
        cleanResponseCache(AT_CMD_CGDCONT);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCGDCONT(
            g_ACICmdSrc,
            pdp_context_array,
            cid_array);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CGDCONT, TIMEOUT_LONG);
        if (res == E_GEN_OK) {

        }
        CALL_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PlusCGDCONT: {
        CALL_LOCK();
        struct VM_CMD_sAT_PlusCGDCONT *pdp = &command->sAT_PlusCGDCONT;
        T_PDP_CONTEXT pdp_context;
        memset(&pdp_context, 0, sizeof(pdp_context));
        pdp_context.pdp_addr.ctrl_ip_address = NAS_is_ip_not_present;
        pdp_context.d_comp = PDP_CONTEXT_D_COMP_OMITTED;
        pdp_context.h_comp = PDP_CONTEXT_H_COMP_OMITTED;
        pdp_context.p_cid = PDP_CONTEXT_CID_OMITTED;
        strcpy(pdp_context.pdp_type, pdp->pdp_context.pdp_type);
        strcpy(pdp_context.pdp_apn, pdp->pdp_context.pdp_apn);
        pdp_context.pdp_addr.ctrl_ip_address =
            (T_NAS_ctrl_ip_address)pdp->pdp_context.pdp_addr.ctrl_ip_address;
        memcpy(&pdp_context.pdp_addr.ip_address,
            &pdp->pdp_context.pdp_addr.ip_address,
            sizeof(pdp_context.pdp_addr.ip_address));
        pdp_context.d_comp = pdp->pdp_context.d_comp;
        pdp_context.h_comp = pdp->pdp_context.h_comp;
        pdp_context.p_cid = pdp->pdp_context.p_cid;
        cleanResponseCache(AT_CMD_CGDCONT);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCGDCONT(
            g_ACICmdSrc,
            pdp->cid,
            &pdp_context);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CGDCONT, TIMEOUT_LONG);
        CALL_UNLOCK();
        return res;
    }
        break;
    case VM_IOCTRL_sAT_Dn_GPRS: {
        CALL_LOCK();
        nu_ACI_GetCommand()->sAT_PercentCGAATT(
            g_ACICmdSrc,
            CGAATT_ATTACH_MODE_AUTOMATIC,
            CGAATT_DETACH_MODE_OFF);

        T_ACI_RETURN ret;

        U8 cids[PDP_CONTEXT_CID_MAX];
        memset(cids, PDP_CONTEXT_CID_INVALID, PDP_CONTEXT_CID_MAX);
        cids[0] = command->sAT_PlusCGACT.cid;
        cleanResponseCache(AT_CMD_CGACT);
        ret = nu_ACI_GetCommand()->sAT_PlusCGACT(
            g_ACICmdSrc,
            (T_CGACT_STATE)1,
            cids);
        VM_LOG("VM_LOG: sAT_PlusCGACT -> ret.%d\n", ret);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CGACT, 20000);
        if (res != E_GEN_OK) {
            CALL_UNLOCK();
            return E_GEN_INTERNAL;
        }
        ret = nu_ACI_GetCommand()->sAT_PlusCGDATA(
            g_ACICmdSrc,
            "M-IP",
            cids);
        VM_LOG("VM_LOG: sAT_PlusCGDATA -> ret.%d\n", ret);
        CALL_UNLOCK();
        return E_GEN_OK;
    }
        break;

    case VM_IOCTRL_sAT_PlusCGACT: {
        CALL_LOCK();
        nu_ACI_GetCommand()->sAT_PercentCGAATT(
            g_ACICmdSrc,
            CGAATT_ATTACH_MODE_AUTOMATIC,
            CGAATT_DETACH_MODE_OFF);

        U8 cids[2] = {command->sAT_PlusCGACT.cid, PDP_CONTEXT_CID_INVALID};
        cleanResponseCache(AT_CMD_CGACT);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCGACT(
            g_ACICmdSrc,
            (T_CGACT_STATE)command->sAT_PlusCGACT.state,
            cids);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CGACT, TIMEOUT_NORMAL);
        if (res != E_GEN_OK) {
            CALL_UNLOCK();
            return E_GEN_INTERNAL;
        }
        CALL_UNLOCK();
        return E_GEN_OK;
    }
        break;

    case VM_IOCTRL_sAT_PercentCGPCO : {
        CALL_LOCK();
        nu_ACI_GetCommand()->sAT_PercentCGPCO(
            g_ACICmdSrc,
            command->sAT_PercentCGPCO.cid,
            command->sAT_PercentCGPCO.protocol,
            command->sAT_PercentCGPCO.user,
            command->sAT_PercentCGPCO.pwd,
            command->sAT_PercentCGPCO.dns1,
            command->sAT_PercentCGPCO.dns2);
        CALL_UNLOCK();
        return E_GEN_OK;
    }

    case VM_IOCTRL_sAT_PlusCGATT : {
        CALL_LOCK();
        nu_ACI_GetCommand()->sAT_PercentCGAATT(
            g_ACICmdSrc,
            CGAATT_ATTACH_MODE_AUTOMATIC,
            CGAATT_DETACH_MODE_OFF);

        nu_ACI_GetCommand()->sAT_Abort(
            g_ACICmdSrc,
            AT_CMD_CGATT);
        cleanResponseCache(AT_CMD_CGATT);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCGATT(
            g_ACICmdSrc,
            (T_CGATT_STATE)command->sAT_PlusCGATT.state);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CGATT, TIMEOUT_NORMAL);
        if (res != E_GEN_OK) {
            CALL_UNLOCK();
            return E_GEN_INTERNAL;
        }
        CALL_UNLOCK();
        return E_GEN_OK;
    }

    case VM_IOCTRL_qAT_PlusCGATT : {
        CALL_LOCK();
        T_CGATT_STATE state;
        cleanResponseCache(AT_CMD_CGATT);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCGATT(
            g_ACICmdSrc,
            &state);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CGATT, TIMEOUT_NORMAL);
        if (res != E_GEN_OK) {
            CALL_UNLOCK();
            return E_GEN_INTERNAL;
        }
        response->qAT_PlusCGATT.state = state;
        CALL_UNLOCK();
        return E_GEN_OK;
    }

    case VM_IOCTRL_sAT_PercentSATC: {
        SIM_LOCK();
        VM_CMD_sAT_PercentSATC *p = &command->sAT_PercentSATC;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PercentSATC len.%d\n", p->length);
        //nu_ACI_GetCommand()->sAT_Abort(
        //    g_ACICmdSrc,
        //    AT_CMD_SATC);
        cleanResponseCache(AT_CMD_SATC);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PercentSATC(
            g_ACICmdSrc, p->length, (UBYTE*)p->satProfile);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_SATC, TIMEOUT_NORMAL);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PercentSATE: {
        SIM_LOCK();
        VM_CMD_sAT_PercentSATE *p = &command->sAT_PercentSATE;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PercentSATE len.%d\n", p->length);
        //nu_ACI_GetCommand()->sAT_Abort(
        //    g_ACICmdSrc,
        //    AT_CMD_SATE);
        cleanResponseCache(AT_CMD_SATE);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PercentSATE(
            g_ACICmdSrc, p->length, (UBYTE*)p->satCmd);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_SATE, TIMEOUT_NORMAL, response);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PercentSATR: {
        SIM_LOCK();
        VM_CMD_sAT_PercentSATR *p = &command->sAT_PercentSATR;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PercentSATR len.%d\n", p->length);
        //nu_ACI_GetCommand()->sAT_Abort(
        //    g_ACICmdSrc,
        //    AT_CMD_SATR);
        cleanResponseCache(AT_CMD_SATR);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PercentSATR(
            g_ACICmdSrc, p->length, (UBYTE*)p->satRsp);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_SATR, TIMEOUT_NORMAL);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PercentSATT: {
        SIM_LOCK();
        VM_CMD_sAT_PercentSATT *p = &command->sAT_PercentSATT;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PercentSATT -> p->cause.%d\n",
            p->cause);
        //nu_ACI_GetCommand()->sAT_Abort(
        //    g_ACICmdSrc,
        //    AT_CMD_SATT);
        cleanResponseCache(AT_CMD_SATT);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PercentSATT(
            g_ACICmdSrc, (T_ACI_SATT_CS)p->cause);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_SATT, TIMEOUT_NORMAL);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PlusCCWA: {
        CALL_LOCK();
        VM_CMD_sAT_PlusCCWA *p = &command->sAT_PlusCCWA;
        cleanResponseCache(AT_CMD_CCWA);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCCWA(
            g_ACICmdSrc, (T_ACI_CCWA_MOD)p->mode, (T_ACI_CLASS)p->class_type);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCCWA -> mode.%d class_type.%d ret.%d\n",
            p->mode, p->class_type, ret);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CCWA, TIMEOUT_LONG);
        CALL_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_qAT_PlusCCWA: {
        CALL_LOCK();
        VM_CMD_qAT_PlusCCWA *p = &command->qAT_PlusCCWA;
        VM_LOG("VM_LOG: VM_CMD_qAT_PlusCCWA  -> class_type.%d\n",
            p->class_type);
        cleanResponseCache(AT_CMD_CCWA);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCCWA(
            g_ACICmdSrc, (T_ACI_CLASS)p->class_type);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CCWA, TIMEOUT_LONG, response);
        CALL_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_qAT_PlusCOLP: {
        CALL_LOCK();
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCOLP  -> not imp\n");
        CALL_UNLOCK();
        return E_NOT_IMPLEMENTED;
    }
        break;

    case VM_IOCTRL_qAT_PlusCLIP: {
        CALL_LOCK();
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCLIP  -> not imp\n");
        CALL_UNLOCK();
        return E_NOT_IMPLEMENTED;
    }
        break;

    case VM_IOCTRL_sAT_PlusCLIR: {
        CALL_LOCK();
        VM_CMD_sAT_PlusCLIR *p = &command->sAT_PlusCLIR;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCLIR(
            g_ACICmdSrc, (T_ACI_CLIR_MOD)p->mode);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCLIR -> mode.%d ret.%d\n",
            p->mode, ret);
        CALL_UNLOCK();
        return ret;
    }
        break;

    case VM_IOCTRL_qAT_PlusCLIR: {
        CALL_LOCK();
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCLIR\n");
        cleanResponseCache(AT_CMD_CLIR);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCLIR(
            g_ACICmdSrc, NULL, NULL);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CLIR, TIMEOUT_NORMAL, response);
        CALL_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PlusCCFC: {
        CALL_LOCK();
        VM_CMD_sAT_PlusCCFC *p = &command->sAT_PlusCCFC;
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCCFC reason.%d mode.%d number.%s\n",
            p->reason, p->mode, p->number);

        T_ACI_TOA type;
        type.ton = (T_ACI_TOA_TON)p->ton;
        type.npi = (T_ACI_TOA_NPI)p->npi;

        T_ACI_TOS satype;
        satype.tos = (T_ACI_TOS_TOS)p->tos;
        satype.oe = (T_ACI_TOS_OE)p->oe;
        cleanResponseCache(AT_CMD_CCFC);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCCFC(
            g_ACICmdSrc,
            (T_ACI_CCFC_RSN)p->reason,
            (T_ACI_CCFC_MOD)p->mode,
            p->number,
            &type,
            (T_ACI_CLASS)p->class_type,
            NULL, //p->subaddr,
            NULL, //&satype,
            (SHORT)p->time);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CCFC, TIMEOUT_LONG);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCCFC -> res.%x ret.%d\n",
            res, ret);
        CALL_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_qAT_PlusCCFC: {
        CALL_LOCK();
        VM_CMD_qAT_PlusCCFC *p = &command->qAT_PlusCCFC;
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCCFC reason.%d class_type.%d\n",
            p->reason, p->class_type);
        cleanResponseCache(AT_CMD_CCFC);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCCFC(
            g_ACICmdSrc,
            (T_ACI_CCFC_RSN)p->reason,
            (T_ACI_CLASS)p->class_type);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CCFC, TIMEOUT_LONG, response);
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCCFC -> res.%x ret.%d reason.%d class_type.%d\n",
            res, ret, p->reason, p->class_type);
        CALL_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_tAT_PlusCOPS: {
        CALL_LOCK();
        VM_LOG("VM_LOG: VM_IOCTRL_tAT_PlusCOPS\n");

        response->tAT_PlusCOPS.count = 0;
        cleanResponseCache(AT_CMD_COPS);
        g_current_atcmd = AT_CMD_COPS;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->tAT_PlusCOPS(
            g_ACICmdSrc, 0, NULL, NULL);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_COPS, TIMEOUT_NETWORK, response);
        VM_LOG("VM_LOG: VM_IOCTRL_tAT_PlusCOPS -> res.%x ret.%d count.%d\n",
            res, ret, response->tAT_PlusCOPS.count);
        if ((E_GEN_OK == res) && (0 == response->tAT_PlusCOPS.count))
            res = E_GEN_INTERNAL;
        g_current_atcmd = AT_CMD_NONE;
        CALL_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_sAT_PlusCPOL: {
        SIM_LOCK();
        VM_CMD_sAT_PlusCPOL *p = &command->sAT_PlusCPOL;

        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPOL index.%d,fmt.%d,oper.%s\n",
            p->oper.index, p->oper.format, p->oper.oper);

        char *pOper = p->oper.oper;
        if ((T_ACI_CPOL_FRMT)p->oper.format == CPOL_FRMT_NotPresent
            && *pOper == 0) {
            pOper = NULL;
        }
        cleanResponseCache(AT_CMD_CPOL);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PlusCPOL(g_ACICmdSrc,
                                    p->oper.index,
                                    (T_ACI_CPOL_FRMT)p->oper.format,
                                    pOper,
                                    -1,
                                    CPOL_MOD_NotPresent);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPOL, TIMEOUT_NORMAL);
        VM_LOG("VM_LOG: VM_IOCTRL_sAT_PlusCPOL -> res.%x ret.%d\n",
            res, ret);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_qAT_PlusCPOL: {
        SIM_LOCK();
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCPOL\n");
        cleanResponseCache(AT_CMD_CPOL);
        T_ACI_RETURN ret = nu_ACI_GetCommand()->qAT_PlusCPOL(g_ACICmdSrc,
                                    0, NULL, NULL, CPOL_MOD_NotPresent);
        int res = getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CPOL, TIMEOUT_NETWORK, response);
        VM_LOG("VM_LOG: VM_IOCTRL_qAT_PlusCPOL -> res.%x ret.%d,count.%d\n",
            res, ret, response->qAT_PlusCPOL.count);
        SIM_UNLOCK();
        return res;
    }
        break;

    case VM_IOCTRL_START: {
        SIM_LOCK();
        g_VMStatus.monitorIndicator = 1;

        // Set SAT Profile
        UBYTE satProfile[11];
        satProfile[0] = 0x7F;
        satProfile[1] = 0xFF;
        satProfile[2] = 0xFF;
        satProfile[3] = 0xFF;
        satProfile[4] = 0x7F;
        satProfile[5] = 0x03;
        satProfile[6] = 0x00;
        satProfile[7] = 0xBF;
        satProfile[8] = 0x7F;
        satProfile[9] = 0x03;
        satProfile[10] = 0xFF;
        T_ACI_RETURN ret = nu_ACI_GetCommand()->sAT_PercentSATC(
            g_ACICmdSrc,
            sizeof(satProfile),
            satProfile);

        cleanResponseCache(AT_CMD_CFUN);
        ret = nu_ACI_GetCommand()->sAT_PlusCFUN(
            g_ACICmdSrc,
            CFUN_FUN_Full,
            CFUN_RST_NoReset);
        getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CFUN, TIMEOUT_LONG);
        cleanResponseCache(AT_CMD_CFUN);
        ret = nu_ACI_GetCommand()->sAT_PlusCFUN(
            g_ACICmdSrc,
            CFUN_FUN_Disable_TX_RX_RF,
            CFUN_RST_NoReset);
        getGeneralReturn(
            ret, /* VM_GR_OK | VM_GR_CME, */ AT_CMD_CFUN, TIMEOUT_LONG);

        //enable time and date report
        nu_ACI_GetCommand()->sAT_PercentCTZV(g_ACICmdSrc, PCTZV_MODE_ON);

        SIM_UNLOCK();
    }
        break;

    case VM_IOCTRL_EXIT: {
        SIM_LOCK();
        g_VMStatus.monitorIndicator = 0;
        g_indicatorEvent.Notify(1);
        SIM_UNLOCK();
    }
        break;

    case VM_IOCTRL_SyncTimeEnabled: {
        g_SyncTimeEnabled = 1;
    }
        break;

    case VM_IOCTRL_SyncTimeDisabled: {
        g_SyncTimeEnabled = 0;
    }
        break;

    default:
        break;
    }
    return 0;
}

int CALLACI_getIndicatorMessage(
    /* [out] */ MemoryBuf * getData)
{
    VM_INDICATOR *ind = (VM_INDICATOR *)getData->GetPayload();
    if (getIndicatorMessage(ind) == 0) {
		if (ind->type == VM_INDT_PlusCCLK) {
			VM_LOG("VM_LOG: SyncNetTime g_SyncTimeElapsed.%d\n", g_SyncTimeElapsed);
			if (g_SyncTimeElapsed != 0) {
				UpdataRTCTime(g_SyncTimeElapsed);
				g_SyncTimeElapsed = 0;
			    SystemTime systemTime;
				DzGetSystemTime(&systemTime);
			    VM_LOG("VM_LOG: -> SyncNetTime After UpdataRTCTime systemTime.%d\n",
			                       systemTime.seconds);
		    }
		}
        return E_GEN_OK;
    }
    return E_GEN_FAIL;
}

